package p2p

import (
	"bufio"
	"context"
	"fmt"
	"osiris/logger"

	peer "github.com/libp2p/go-libp2p/core/peer"
	"github.com/libp2p/go-libp2p/core/protocol"
)

// MulticastProtocol 广播协议的基类
type MulticastProtocol struct {

	// StaticExcluded 多播时跳过的节点列表(始终跳过，由protocol创建时指定，且之后都不会修改)
	StaticExcluded map[peer.ID]bool

	// DynamicExcluded 多播时跳过的节点列表(可动态修改，excluded只生效一次)
	DynamicExcluded map[peer.ID]bool
}

// isPeerExcluded 判断是否为多播排除在外的节点
//
//	@receiver protocol
//	@param peerID
//	@return bool
func (protocol MulticastProtocol) isPeerExcluded(peerID peer.ID) bool {
	if peerID == GetSelfID() {
		return true
	}

	if _, exist := protocol.StaticExcluded[peerID]; exist {
		return true
	}

	if _, exist := protocol.DynamicExcluded[peerID]; exist {
		//只生效一次
		delete(protocol.DynamicExcluded, peerID)
		return true
	}

	return false
}

// openMultiStream 开启多播
//
//	@receiver protocol
//	@param jsonStr
func (protocol MulticastProtocol) openMultiStream(protocolID protocol.ID, jsonStr string) {
	peerIDs := GetPeerIDs()
	for _, peerID := range peerIDs {
		if protocol.isPeerExcluded(peerID) {
			logger.Info(map[string]interface{}{fmt.Sprintf("[p2p] [Open MultiStream %s] Ha.NewStream", protocolID): fmt.Sprintf("excluded peer.ID: %s", peerID.String())})
			continue
		}

		go func(targetPeerID peer.ID) {
			s, err := ha.NewStream(context.Background(), targetPeerID, protocolID)
			if err != nil {
				logger.Error(map[string]interface{}{fmt.Sprintf("[p2p] [Open MultiStream %s] Ha.NewStream", protocolID): err})
				return
			} else {
				logger.Info(map[string]interface{}{fmt.Sprintf("[p2p] [Open MultiStream %s] Ha.NewStream", protocolID): "success"})
			}

			// Create a buffered stream so that read and writes are non blocking.
			rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
			rw.WriteString(fmt.Sprintf("%s\n", jsonStr))
			rw.Flush()
			s.Close()
		}(peerID)
	}
}
